#include "./config.h"

namespace framework
{
//Config::ConfigVarMap Config::s_datas;
static framework::Logger::ptr g_logger = FRAMEWORK_LOG_NAME("system");

//将yum的键值和数据放到list中
static void ListAllMember(const std::string& prefix, const YAML::Node& node,
                            std::list<std::pair<std::string, const YAML::Node>>& output)
{
    if(prefix.find_first_not_of("abcdefghikjlmnopqrstuvwxyz._012345678") != std::string::npos)
    {
        FRAMEWORK_LOG_ERROR(FRAMEWORK_LOG_ROOT()) << "Config invalid name: " << prefix << " : " << node;
        return;
    }

    output.push_back(std::make_pair(prefix, node));
    if(node.IsMap())
    {
        for(auto it = node.begin(); it != node.end(); ++it)
        {
            ListAllMember(prefix.empty() ? it->first.Scalar() : prefix + "." + it->first.Scalar(),
                                    it->second, output);
        }
    }
}


//查找配置参数,返回配置参数的基类   name:配置参数名称
ConfigVarBase::ptr Config::LookupBase(const std::string& name)
{
    RWMutexType::ReadLock lock(GetMutex());
    auto it = GetDatas().find(name);
    return it == GetDatas().end() ? nullptr : it->second;
}

//使用YAML::Node初始化配置模块
void Config::LoadFromYaml(const YAML::Node& root)
{
    std::list<std::pair<std::string, const YAML::Node>> all_nodes;
    ListAllMember("", root, all_nodes);

    for(const auto& i : all_nodes)
    {  
        std::string key = i.first;
        if(key.empty())
        {
            continue;
        }

        std::transform(key.begin(), key.end(), key.begin(), ::tolower);
        ConfigVarBase::ptr var = LookupBase(key);

        // std::cout << "=========================================" << std::endl;
        // std::cout << key << "  --  " << std::endl << i.second << std::endl;
        // std::cout << "=========================================" << std::endl;

        if(var)
        {
            if(i.second.IsScalar())
            {
                var->fromString(i.second.Scalar());
            }
            else
            {
                std::stringstream ss;
                ss << i.second;
                var->fromString(ss.str());
            }
        }
    }
}

//遍历配置模块里所以配置项
void Config::Visit(std::function<void(ConfigVarBase::ptr)> cb)
{
    RWMutexType::ReadLock lock(GetMutex());
    ConfigVarMap& m = GetDatas();
    for(auto it = m.begin(); it != m.end(); ++it) 
    {
        cb(it->second);
    }
}


}

